package com.ezops.poc.validations;

import java.util.LinkedList;
import java.util.List;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;

import com.ezops.model.EzopsOTModel;
import com.ezops.poc.validations.parser.ValidationFileParser;
import com.ezops.poc.validations.validators.IValidators;

/**
 * Test class to test Validation processor functions.
 * 
 * @author vgaurav
 * 
 */

@RunWith(MockitoJUnitRunner.class)
// @ContextConfiguration(classes = { TestContext.class, WebAppContext.class })
// @ContextConfiguration(locations={"classpath:META-INF/spring/camel-context.xml"})
// @WebAppConfiguration
public class ValidationProcessorTestCase {

	private MockMvc mockMvc;

	@Mock
	private ValidationFileParser parser;

	@InjectMocks
	@Autowired
	private ValidationProcessor validationProcessor;

	@Autowired
	private WebApplicationContext webApplicationContext;

	@Before
	public void setUp() {
		Mockito.reset(parser);
		// mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
		// .build();
		MockitoAnnotations.initMocks(this);

	}

	@Test
	public void testExecuteEzopsValidationRule_MandatorySingleField() {

		List<LinkedList<IValidators>> allValidators = ValidationProcessTestFixture
				.getMandatoryValidatorForAccrualField();
		Mockito.when(parser.getAllValidators()).thenReturn(allValidators);

		EzopsOTModel model = new EzopsOTModel();
		model.setProductType("FX");
		model.setAssetId(5);
		// No Field value for accrual

		EzopsValidationException retuenedException;
		retuenedException = validationProcessor
				.executeEzopsValidationRule(model);
		Assert.assertNotNull(retuenedException);
		Assert.assertTrue(
				"Returned validation exception doesn't report correct field",
				retuenedException.getFieldErrors().get(0).getFieldName()
						.equals("accrual"));

	}

	@Test
	public void testExecuteEzopsValidationRule_RangeSingleField() {

		List<LinkedList<IValidators>> allValidators = ValidationProcessTestFixture
				.getRangeValidatorFoProductCouponRateField();
		Mockito.when(parser.getAllValidators()).thenReturn(allValidators);

		EzopsOTModel model = new EzopsOTModel();
		model.setProductType("FX");
		model.setAssetId(5);
		model.setProductCouponRate("101");

		EzopsValidationException retuenedException = validationProcessor
				.executeEzopsValidationRule(model);
		Assert.assertNotNull(retuenedException);
		Assert.assertTrue(
				"Returned validation exception doesn't report correct field",
				retuenedException.getFieldErrors().get(0).getFieldName()
						.equals("productCouponRate"));

	}

	@Test
	public void testExecuteEzopsValidationRule_SameFieldMultiRule() {

		List<LinkedList<IValidators>> allValidators = ValidationProcessTestFixture
				.getMultipleValidatorsForSameField();
		Mockito.when(parser.getAllValidators()).thenReturn(allValidators);

		EzopsOTModel model = new EzopsOTModel();
		model.setProductType("CDS");
		model.setAssetId(4);
		model.setProductCouponRate("");

		EzopsValidationException retuenedException = validationProcessor
				.executeEzopsValidationRule(model);
		Assert.assertNotNull(retuenedException);
		Assert.assertTrue(
				"Returned validation exception doesn't report correct field",
				retuenedException.getFieldErrors().get(0).getFieldName()
						.equals("productCouponRate"));

		EzopsOTModel nextModel = new EzopsOTModel();
		nextModel.setProductType("Bond");
		nextModel.setAssetId(1);
		nextModel.setProductCouponRate("");

		EzopsValidationException retuenedNextException = validationProcessor
				.executeEzopsValidationRule(nextModel);
		Assert.assertNull(retuenedNextException);

	}

	@Test
	public void testExecuteEzopsValidationRule_MandatoryMultiRowSameFieldRule() {

		List<LinkedList<IValidators>> allValidators = ValidationProcessTestFixture
				.getMultipleValidatorsForSameField();
		Mockito.when(parser.getAllValidators()).thenReturn(allValidators);

		EzopsOTModel model = new EzopsOTModel();
		model.setProductType("CDS");
		model.setAssetId(4);
		model.setProductCouponRate("");

		EzopsValidationException retuenedException = validationProcessor
				.executeEzopsValidationRule(model);
		Assert.assertNotNull(retuenedException);
		Assert.assertTrue(
				"Returned validation exception doesn't report correct field",
				retuenedException.getFieldErrors().get(0).getFieldName()
						.equals("productCouponRate"));

		EzopsOTModel nextModel = new EzopsOTModel();
		nextModel.setProductType("Bond");
		nextModel.setAssetId(1);
		nextModel.setProductCouponRate("");

		EzopsValidationException retuenedNextException = validationProcessor
				.executeEzopsValidationRule(nextModel);
		Assert.assertNull(retuenedNextException);

	}

	@Test
	public void testExecuteEzopsValidationRule_MandatoryTypeRule() {

		List<LinkedList<IValidators>> allValidators = ValidationProcessTestFixture
				.getMandatoryAndTypeValidatorForTickerSymbolField();
		Mockito.when(parser.getAllValidators()).thenReturn(allValidators);

		EzopsOTModel model = new EzopsOTModel();
		model.setProductType("CDS");
		model.setAssetId(4);
		model.setProductTickerSymbol("asde");

		EzopsValidationException retuenedException = validationProcessor
				.executeEzopsValidationRule(model);
		Assert.assertNull(retuenedException);

		EzopsOTModel nextModel = new EzopsOTModel();
		nextModel.setProductType("CDS");
		nextModel.setAssetId(4);
		nextModel.setProductTickerSymbol("1234323");

		EzopsValidationException retuenedNextException = validationProcessor
				.executeEzopsValidationRule(nextModel);
		Assert.assertNull(retuenedNextException);

		EzopsOTModel model2 = new EzopsOTModel();
		model2.setProductType("CDS");
		model2.setAssetId(4);
		model2.setProductTickerSymbol("wswswswsd");

		EzopsValidationException retuenedException2 = validationProcessor
				.executeEzopsValidationRule(model2);
		Assert.assertNull(retuenedException2);

	}

	@Test
	public void testExecuteEzopsValidationRule_DecimalTypeRule() {

		List<LinkedList<IValidators>> allValidators = ValidationProcessTestFixture
				.getDecimalTypeValidatorForSettleAmoutField();
		Mockito.when(parser.getAllValidators()).thenReturn(allValidators);

		EzopsOTModel model = new EzopsOTModel();
		model.setProductType("CDS");
		model.setAssetId(4);
		model.setSettleAmount("233.98");

		EzopsValidationException retuenedException = validationProcessor
				.executeEzopsValidationRule(model);
		Assert.assertNull(retuenedException);

		EzopsOTModel nextModel = new EzopsOTModel();
		nextModel.setProductType("CDS");
		nextModel.setAssetId(4);
		nextModel.setSettleAmount("1234323");

		EzopsValidationException retuenedNextException = validationProcessor
				.executeEzopsValidationRule(nextModel);
		Assert.assertNotNull(retuenedNextException);

		EzopsOTModel model2 = new EzopsOTModel();
		model2.setProductType("CDS");
		model2.setAssetId(4);
		model2.setSettleAmount("11.234");

		EzopsValidationException retuenedException2 = validationProcessor
				.executeEzopsValidationRule(model2);
		Assert.assertNotNull(retuenedException2);

	}

	@Test
	public void testExecuteEzopsValidationRule_FixedTypeRule() {

		List<LinkedList<IValidators>> allValidators = ValidationProcessTestFixture
				.getFixedTypeValidatorForBuySellField();
		Mockito.when(parser.getAllValidators()).thenReturn(allValidators);

		EzopsOTModel model = new EzopsOTModel();
		model.setProductType("CDS");
		model.setAssetId(4);
		model.setBuySell("buy");

		EzopsValidationException retuenedException = validationProcessor
				.executeEzopsValidationRule(model);
		Assert.assertNull(retuenedException);

		EzopsOTModel nextModel = new EzopsOTModel();
		nextModel.setProductType("CDS");
		nextModel.setAssetId(4);
		nextModel.setBuySell("asdasd");

		EzopsValidationException retuenedNextException = validationProcessor
				.executeEzopsValidationRule(nextModel);
		Assert.assertNotNull(retuenedNextException);

	}

	@Test
	public void testExecuteEzopsValidationRule_DateTypeRule() {

		List<LinkedList<IValidators>> allValidators = ValidationProcessTestFixture
				.getDateTypeValidatorForTradingDayField();
		Mockito.when(parser.getAllValidators()).thenReturn(allValidators);

		EzopsOTModel model = new EzopsOTModel();
		model.setProductType("CDS");
		model.setAssetId(4);
		model.setTradingDay("01/01/2014");

		EzopsValidationException retuenedException = validationProcessor
				.executeEzopsValidationRule(model);
		Assert.assertNull(retuenedException);

		EzopsOTModel nextModel = new EzopsOTModel();
		nextModel.setProductType("CDS");
		nextModel.setAssetId(4);
		nextModel.setBuySell("2014/22/12");

		EzopsValidationException retuenedNextException = validationProcessor
				.executeEzopsValidationRule(nextModel);
		Assert.assertNotNull(retuenedNextException);

	}

	@Test
	public void testExecuteEzopsValidationRule_AlphanumericLessThanTypeRule() {

		List<LinkedList<IValidators>> allValidators = ValidationProcessTestFixture
				.getAlphaTypeValidatorForTickerSymbolField();
		Mockito.when(parser.getAllValidators()).thenReturn(allValidators);

		EzopsOTModel model = new EzopsOTModel();
		model.setProductTickerSymbol("Stad");
		model.setAssetId(4);

		EzopsValidationException retuenedException = validationProcessor
				.executeEzopsValidationRule(model);
		Assert.assertNull(retuenedException);

		EzopsOTModel model1 = new EzopsOTModel();
		model1.setBookId("asee");
		model1.setAssetId(4);

		// just chk one rule
		allValidators.get(0).remove(0);
		EzopsValidationException retuenedException1 = validationProcessor
				.executeEzopsValidationRule(model1);
		Assert.assertNull(retuenedException1);

	}

}
